# THANKS TO:
# https://github.com/yaronzz/Tidal-Media-Downloader
# https://github.com/lucaslg26/TidalAPI
# https://pypi.org/project/tidalapi

from urllib.request import urlopen
import requests
import uuid
import pyaes

import tidal.track_stream
import tidal.track
import tidal.album
import tidal.artist

PRIVATE_API_URL = "https://api.tidalhifi.com/v1/%s"

class Tidal:
  def __init__(self):
    self.session = requests.Session()
    self.session_id = None
    self.country_code = "US" # should we set this to what the server says?
    self.user_id = None
    self.username = None

  def call_private_api(
      self, path, params = {}, headers = {},
      post = False, form = False
  ):
    url = PRIVATE_API_URL % path

    params["countryCode"] = self.country_code

    if self.session_id != None:
      headers["X-Tidal-SessionId"] = self.session_id
      #params["sessionId"] = self.session_id

    args = {
      "params": params,
      "headers": headers
    }
    if form:
      args["data"] = form

    response = None
    if post:
      response = self.session.post(url, **args)
    else:
      response = self.session.get(url, **args)

    json = response.json()
    if "status" in json and json["status"] == 404:
      raise 'not found'

    return response

  def login(self, username, password, bymobile = False):
    # more info about tokens: https://github.com/arnesongit/plugin.audio.tidal2/blob/master/resources/lib/koditidal.py#L781
    # if it's dead: https://ghostbin.com/paste/y9g6e
    token = "BI218mwp9ERZ3PFI"

    data = self.call_private_api(
      "login/username",
      post = True,
      params = {"token": token},
      form = {
        "username": username,
        "password": password,
        "clientUniqueKey": str(uuid.uuid4()).replace('-', '')[16:]
      }
    ).json()

    if "status" in data:
      if data["status"] == 401:
        raise 'username or password is wrong'
      else:
        raise 'unknown error getting session id'
    else:
      self.session_id = data["sessionId"]
      self.user_id = data["userId"]
      #self.country_code = data["countryCode"]

    # get user profile
    data = self.call_private_api("users/%i" % self.user_id).json()
    if "status" in data and not data["status"] == 200:
      raise 'unknown error when getting profile'

    self.username = data["username"]

    return {"username": username}

  def get_stream_info(self, track_id, quality):
    return self.call_private_api(
      "tracks/%i/streamUrl" % track_id,
      params = {"soundQuality": quality}
    )
  def get_stream(self, track_id, quality):
    return tidal.track_stream.TidalTrackStream.grab_or_create(
      track_id,
      raw_data = self.get_stream_info(track_id, quality).json()
    )

  def get_track_data(self, track_id):
    return self.call_private_api("tracks/%i" % track_id)
  def get_track(self, track_id):
    return tidal.track.TidalTrack.grab_or_create(
      track_id,
      raw_data = self.get_track_data(track_id).json()
    )

  def get_album_data(self, album_id):
    return self.call_private_api("albums/%i" % album_id)
  def get_album_tracks_data(self, album_id):
    return self.call_private_api("albums/%i/tracks" % album_id)
  def get_album_full_data(self, album_id):
    return {**self.get_album_data(album_id).json(),
            "songs": self.get_album_tracks_data(album_id).json()}
  def get_album(self, album_id):
    return tidal.album.TidalAlbum.grab_or_create(
      album_id,
      raw_data = self.get_album_full_data(album_id),
    )

  def get_artist_data(self, artist_id):
    return self.call_private_api("artists/%i" % album_id)
  def get_artist_albums_data(self, artist_id):
    return self.call_private_api("artists/%i/albums" % album_id)
  def get_artist(self, artist_id):
    return tidal.artist.TidalArtist.grab_or_create(
      artist_id, raw_data = self.get_artist_data(artist_id)
    )

